package com.cmcc.aregister.cs.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;

public class ImageCacheUtil {
    private boolean saveFile = false;
    private String path = "";
    private ImageCallback callback;
    private Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>();

    private Bitmap bitmap;

    public ImageCacheUtil() {

    }
    
    
    private Handler imageHandler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                if (callback != null) {
                    callback.onImageLoaded(bitmap);
                }
            }
        };
    };

    public void setSaveFile(boolean saveFile) {
        this.saveFile = saveFile;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public Bitmap getImage(final String url, final ImageCallback callback) {
        this.callback = callback;
        bitmap = getImageFormCache(url);
        if (bitmap == null) {
            new Thread() {
                public void run() {
                    bitmap = getImageFormUrl(url);
                    imageCache.put(url, new SoftReference<Bitmap>(bitmap));
                };
            }.start();
        }
        else {
            imageHandler.sendEmptyMessage(1);
        }
        return bitmap;
    }

    private Bitmap getImageFormUrl(String url) {
        URL myFileUrl = null;
        try {
            myFileUrl = new URL(encodeURL(url));
            URLConnection conn = myFileUrl.openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            BitmapFactory.Options opts = new BitmapFactory.Options();
            opts.inSampleSize = 4;  
            bitmap = BitmapFactory.decodeStream(is, null, opts);
            //bitmap = BitmapFactory.decodeStream(is);
            is.close();
            if (saveFile) {
                String fileName = getMD5Str(url);
                String filePath = this.path + "/" + fileName;
                saveFile(bitmap, filePath);
            }
            if(bitmap != null){
                bitmap.recycle();
            }
            imageHandler.sendEmptyMessage(1);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    private String encodeURL(String url) {
        int idx = url.lastIndexOf("/") + 1;
        String s = url.substring(0, idx);
        String tmp = url.substring(idx, url.length());
        return s + URLEncoder.encode(tmp);
    }

    private void saveFile(Bitmap bitmap, String fileName) {
        File imageFile = new File(fileName);
        try {
            imageFile.createNewFile();
            FileOutputStream fos = new FileOutputStream(imageFile);
            bitmap.compress(CompressFormat.PNG, 100, fos);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    private Bitmap getImageFormCache(String url) {
        if (imageCache.containsKey(url)) {
            SoftReference<Bitmap> bitmapRef = imageCache.get(url);
            if (bitmapRef != null) {
                bitmap = bitmapRef.get();
                return bitmap;
            }
        }
        String fileName = getMD5Str(url);
        String filePath = path + "/" + fileName;
        try {
            //FileInputStream fis = new FileInputStream(filePath);
            BitmapFactory.Options opts = new BitmapFactory.Options();
            opts.inSampleSize = 4;
            bitmap = BitmapFactory.decodeFile(filePath,opts);
        }
        catch (Exception e) {
            e.printStackTrace();
            bitmap = null;
        }
        return bitmap;
    }
    

    /**
     * MD5 加密
     */
    private static String getMD5Str(String str) {
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.reset();
            messageDigest.update(str.getBytes("UTF-8"));
        }
        catch (NoSuchAlgorithmException e) {
            System.out.println("NoSuchAlgorithmException caught!");
            return null;
        }
        catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }

        byte[] byteArray = messageDigest.digest();
        StringBuffer md5StrBuff = new StringBuffer();
        for (int i = 0; i < byteArray.length; i++) {
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
                md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
            else
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
        }
        return md5StrBuff.toString();
    }

    public interface ImageCallback {
        /**
         * 回调函数
         * @param bitmap: may be null!
         * @param imageUrl
         */
        public void onImageLoaded(Bitmap bitmap);
    }
}
